(本篇文章網誌版:http://shineright.blogspot.tw/2016/12/day-26-camera-aspect-ratio.html)
這個手機遊戲做了25天,都還不能實際以觸控的方式移動角色……今天終於要改變這一點啦!
到很久很久以前寫的PlayerMovement.cs,改一下程式碼:
public class PlayerMovement : MonoBehaviour
{
//-舊程式碼-
public float movementSpeed;
public float minPosX;
public float maxPosX;
//-舊程式碼-
//記錄螢幕中間的X軸
private float midScreenPosX;
void Start()
{
//初始螢幕中間X軸
midScreenPosX = Screen.width / 2f;
}
void Update ()
{
float movement = 0f;
//-舊程式碼- (鍵盤控制移動)
movement = Input.GetAxis ("Horizontal") * movementSpeed * Time.deltaTime;
//-舊程式碼-
//觸控移動角色
if (Input.touchCount > 0) { //玩家正在觸控裝置
Touch touch = Input.GetTouch (0); //取得玩家第一個觸控點
//檢查觸控點的位置在螢幕的左方還是右方,並計算出移動值
movement = (touch.position.x < midScreenPosX ? -1f : 1f) * movementSpeed * Time.deltaTime;
}
//-舊程式碼-
Vector3 newPos = new Vector3 (Mathf.Clamp(transform.position.x + movement, minPosX, maxPosX), transform.position.y, transform.position.z);
transform.position = newPos;
//-舊程式碼-
}
}
首先,我宣告了一個儲存螢幕X軸中線的變數,因為我要讓玩家觸控左半邊螢幕時主角向左移動、觸控右半邊螢幕時主角向右移動。
在Start()
函數,我以Screen.width
取得玩家裝置的螢幕寬度,除以2(也就是中間線),指定給midScreenPosX
。
觸控的重頭戲在Update()
函數中。Input.touchCount
會回傳目前玩家在裝置上的總觸控數,Input.touchCount > 0
表示玩家至少有一根手指頭放在螢幕上。Input.GetTouch(int index)
則用來取得玩家的觸控點,index
值表示觸控點的索引值。例如,玩家把食指放在螢幕上不放開,接著又把中指放在螢幕上,Input.touchCount
就會回傳2(兩個觸控點),Input.GetTouch(0)
會回傳食指的觸控點,Input.GetTouch(1)
會回傳中指的觸控點。
在此我只在乎玩家第一個在螢幕上的觸控點,也就是Input.GetTouch(0)
。Touch
類別的position
成員可取得觸控點的位置座標。我檢查touch.position.x < midScreenPosX
(觸控點的X座標是否小於螢幕的中間線),如果成立,則把最終的移動數值乘一個-1f
(向左移)。不成立則乘不影響數值的1f
。
回到Unity Editor,但是……該如何測試觸控呢?首先,準備好iPhone或Android手機,到App Store/Play Store下載Unity Remote 5,點開,會看到以下畫面:
跟著指示到上方選單選Edit→Project Settings→Editor,接著在Inspector欄中的Unity Remote標題下,把Device選為要測試的裝置。
進入Play Mode,Unity Editor就會把遊戲畫面自動投影在手機上了,Unity Remote 5在手機上的畫值會非常差,但這軟體主要是用來測試觸控的,所以不必太在意。
觸控手機螢幕的左邊和右邊,主角就會跟著左右移動了。
然而,還有一個問題需要解決。如果手機的螢幕不符合9:16的長寬比,顯示出的畫面會被裁掉一些,或多出幾兩條藍色的邊邊。
要解決這點,必須在Main Camera上加上一段Script,讓它適應每個螢幕的長寬比。開一個名為「ScaleCameraInAspectRatio.cs」。
public class ScaleCameraInAspectRatio : MonoBehaviour
{
//長寬比,預設為9:16
public float aspectRatio = 9f / 16f;
void Start()
{
Camera cam = GetComponent<Camera> ();
//裝置螢幕的長寬比
float screenRatio = (float)Screen.width / (float)Screen.height;
//裝置螢幕長寬比和目標長寬比的比值
float scale = screenRatio / aspectRatio;
//裝置螢幕長寬比大於目標長寬比(Main Camera高度應維持,寬度縮小)
if (scale > 1f) {
Rect pixRect = cam.pixelRect; //Main Camera的矩形
//設定寬度
pixRect.width = pixRect.height * aspectRatio;
pixRect.y = 0f;
//顯示寬度要在(過寬的)螢幕正中央,所以要除2
pixRect.x = ((float)Screen.width - pixRect.width) / 2f;
//設定新的Main Camera矩形
cam.pixelRect = pixRect;
}
//裝置螢幕長寬比小於目標長寬比(Main Camera寬度應維持,長度縮小)
else {
Rect pixRect = cam.pixelRect;
//設定高度
pixRect.height = pixRect.width / aspectRatio;
pixRect.x = 0f;
//顯示高度要在(過高的)螢幕正中央,所以要除2
pixRect.y = ((float)Screen.height - pixRect.height) / 2f;
//設定新的Main Camera矩形
cam.pixelRect = pixRect;
}
}
}
這段程式碼有點複雜,主要為了在過寬或過高的螢幕正常顯示,所以必須把Main Camera的長/高設定為和裝置螢幕一樣,再根據目標長寬比調整Main Camera的高/長。
把這段Script加在Main Camera上,並在場景中多加一個Camera,這是為了要讓遊戲在螢幕長寬比不是9:16的裝置上,在螢幕兩側以黑邊蓋住。
把新加Camera的Clear Flags設為Solid Color,Background設為黑色,Projection設為Orthographic,並把Depth設為-2(才能顯示在Main Camera後面)。最後,把Audio Listener Component取消掉,以免場景上同時擁有兩個Audio Listener。
進入Play Mode,現在不論裝置螢幕為何種比例,遊戲都能正常顯示了。
待續。